#include <rtthread.h>

#include <inc/hw_types.h>
#include <inc/hw_memmap.h>
#include <driverlib/gpio.h>
#include <driverlib/sysctl.h>

#include <rtgui/event.h>
#include <rtgui/rtgui_server.h>

#define KEY_ENTER_VALUE  	15
#define KEY_DOWN_VALUE   	29
#define KEY_UP_VALUE     	30
#define KEY_RIGHT_VALUE  	23
#define KEY_LEFT_VALUE   	27

static void GPIO_Configuration(void)
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    //
    // Configure the GPIOs used to read the state of the on-board push buttons.
    //
    GPIOPinTypeGPIOInput(GPIO_PORTE_BASE,
                         GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
    GPIOPadConfigSet(GPIO_PORTE_BASE,
                     GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3,
                     GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_1);
    GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_STRENGTH_2MA,
                     GPIO_PIN_TYPE_STD_WPU);
}

static void key_thread_entry(void *parameter)
{
    rt_time_t next_delay;
    struct rtgui_event_kbd kbd_event;

    GPIO_Configuration();

    /* init keyboard event */
    RTGUI_EVENT_KBD_INIT(&kbd_event);
    kbd_event.mod  = RTGUI_KMOD_NONE;
    kbd_event.unicode = 0;

    while (1)
    {
		int ulData;

		next_delay = 10;
        kbd_event.key = RTGUIK_UNKNOWN;
        kbd_event.type = RTGUI_KEYDOWN;

    	ulData = (GPIOPinRead(GPIO_PORTE_BASE, (GPIO_PIN_0 | GPIO_PIN_1 |
                                            GPIO_PIN_2 | GPIO_PIN_3)) |
              (GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_1) << 3));

        if ( ulData == KEY_ENTER_VALUE )
        {
            rt_thread_delay( next_delay*4 );
            if (ulData == KEY_ENTER_VALUE)
            {
                /* HOME key */
                //rt_kprintf("key_home\n");
                kbd_event.key  = RTGUIK_HOME;
            }
            else
            {
                //rt_kprintf("key_enter\n");
                kbd_event.key  = RTGUIK_RETURN;
            }
        }

        if ( ulData == KEY_DOWN_VALUE )
        {
            //rt_kprintf("key_down\n");
            kbd_event.key  = RTGUIK_DOWN;
        }

        if ( ulData == KEY_UP_VALUE )
        {
            //rt_kprintf("key_up\n");
            kbd_event.key  = RTGUIK_UP;
        }

        if ( ulData == KEY_RIGHT_VALUE )
        {
            //rt_kprintf("key_right\n");
            kbd_event.key  = RTGUIK_RIGHT;
        }

        if ( ulData == KEY_LEFT_VALUE )
        {
            //rt_kprintf("key_left\n");
            kbd_event.key  = RTGUIK_LEFT;
        }

        if (kbd_event.key != RTGUIK_UNKNOWN)
        {
            /* post down event */
            rtgui_server_post_event(&(kbd_event.parent), sizeof(kbd_event));

            next_delay = 10;
            /* delay to post up event */
            rt_thread_delay(next_delay);

            /* post up event */
            kbd_event.type = RTGUI_KEYUP;
            rtgui_server_post_event(&(kbd_event.parent), sizeof(kbd_event));
        }

        /* wait next key press */
        rt_thread_delay(next_delay);
    }
}

void rt_hw_key_init(void)
{
	rt_thread_t key_tid;
    key_tid = rt_thread_create("key",
                               key_thread_entry, RT_NULL,
                               384, 30, 5);

    if (key_tid != RT_NULL) rt_thread_startup(key_tid);
}
